/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2002-2006 * Sleepycat Software. All rights reserved. * * $Id: CheckpointEnd.java,v 1.1 2006/05/06 09:00:36 ckaestne Exp $ */ package com.sleepycat.je.recovery; import java.nio.ByteBuffer; import java.sql.Timestamp; import java.util.Calendar; import com.sleepycat.je.log.LogEntryType; import com.sleepycat.je.log.LogException; import com.sleepycat.je.log.LogReadable; import com.sleepycat.je.log.LogUtils; import com.sleepycat.je.log.LoggableObject; import com.sleepycat.je.utilint.DbLsn; /** * CheckpointEnd encapsulates the information needed by a checkpoint end * log entry. */ public class CheckpointEnd implements LoggableObject, LogReadable { /* * invoker is just a way to tag each checkpoint in the * log for easier log based debugging. It will tell us whether the * checkpoint was invoked by recovery, the daemon, the api, or * the cleaner. */ private String invoker; private Timestamp endTime; private long checkpointStartLsn; private boolean rootLsnExists; private long rootLsn; private long firstActiveLsn; private long lastNodeId; private int lastDbId; private long lastTxnId; private long id; public CheckpointEnd(String invoker, long checkpointStartLsn, long rootLsn, long firstActiveLsn, long lastNodeId, int lastDbId, long lastTxnId, long id) { if (invoker == null) { this.invoker = ""; } else { this.invoker = invoker; } Calendar cal = Calendar.getInstance(); this.endTime = new Timestamp(cal.getTime().getTime()); this.checkpointStartLsn = checkpointStartLsn; this.rootLsn = rootLsn; if (rootLsn == DbLsn.NULL_LSN) { rootLsnExists = false; } else { rootLsnExists = true; } if (firstActiveLsn == DbLsn.NULL_LSN) { this.firstActiveLsn = checkpointStartLsn; } else { this.firstActiveLsn = firstActiveLsn; } this.lastNodeId = lastNodeId; this.lastDbId = lastDbId; this.lastTxnId = lastTxnId; this.id = id; } /* For logging only */ public CheckpointEnd() { checkpointStartLsn = DbLsn.NULL_LSN; rootLsn = DbLsn.NULL_LSN; firstActiveLsn = DbLsn.NULL_LSN; } /* * Logging support for writing to the log */ /** * @see LoggableObject#getLogType */ public LogEntryType getLogType() { return LogEntryType.LOG_CKPT_END; } /** * @see LoggableObject#marshallOutsideWriteLatch * Can be marshalled outside the log write latch. */ public boolean marshallOutsideWriteLatch() { return true; } /** * @see LoggableObject#countAsObsoleteWhenLogged */ public boolean countAsObsoleteWhenLogged() { return false; } /** * @see LoggableObject#postLogWork */ public void postLogWork(long justLoggedLsn) { } /** * @see LoggableObject#getLogSize */ public int getLogSize() { int size = LogUtils.getStringLogSize(invoker) + // invoker LogUtils.getTimestampLogSize() + // endTime LogUtils.getLongLogSize() + // checkpointStartLsn LogUtils.getBooleanLogSize() + // rootLsnExists LogUtils.getLongLogSize() + // firstActiveLsn LogUtils.getLongLogSize() + // lastNodeId LogUtils.getIntLogSize() + // lastDbId LogUtils.getLongLogSize() + // lastTxnId LogUtils.getLongLogSize(); // id if (rootLsnExists) { size += LogUtils.getLongLogSize(); } return size; } /** * @see LoggableObject#writeToLog */ public void writeToLog(ByteBuffer logBuffer) { LogUtils.writeString(logBuffer, invoker); LogUtils.writeTimestamp(logBuffer, endTime); LogUtils.writeLong(logBuffer, checkpointStartLsn); LogUtils.writeBoolean(logBuffer, rootLsnExists); if (rootLsnExists) { LogUtils.writeLong(logBuffer, rootLsn); } LogUtils.writeLong(logBuffer, firstActiveLsn); LogUtils.writeLong(logBuffer, lastNodeId); LogUtils.writeInt(logBuffer, lastDbId); LogUtils.writeLong(logBuffer, lastTxnId); LogUtils.writeLong(logBuffer, id); } /** * @see LogReadable#readFromLog */ public void readFromLog(ByteBuffer logBuffer, byte entryTypeVersion) throws LogException { invoker = LogUtils.readString(logBuffer); endTime = LogUtils.readTimestamp(logBuffer); checkpointStartLsn = LogUtils.readLong(logBuffer); rootLsnExists = LogUtils.readBoolean(logBuffer); if (rootLsnExists) { rootLsn = LogUtils.readLong(logBuffer); } firstActiveLsn = LogUtils.readLong(logBuffer); lastNodeId = LogUtils.readLong(logBuffer); lastDbId = LogUtils.readInt(logBuffer); lastTxnId = LogUtils.readLong(logBuffer); id = LogUtils.readLong(logBuffer); } /** * @see LogReadable#dumpLog */ public void dumpLog(StringBuffer sb, boolean verbose) { sb.append("<CkptEnd invoker=\"").append(invoker); sb.append("\" time=\"").append(endTime); sb.append("\" lastNodeId=\"").append(lastNodeId); sb.append("\" lastDbId=\"").append(lastDbId); sb.append("\" lastTxnId=\"").append(lastTxnId); sb.append("\" id=\"").append(id); sb.append("\" rootExists=\"").append(rootLsnExists); sb.append("\">"); sb.append("<ckptStart>"); sb.append(DbLsn.toString(checkpointStartLsn)); sb.append("</ckptStart>"); if (rootLsnExists) { sb.append("<root>"); sb.append(DbLsn.toString(rootLsn)); sb.append("</root>"); } sb.append("<firstActive>"); sb.append(DbLsn.toString(firstActiveLsn)); sb.append("</firstActive>"); sb.append("</CkptEnd>"); } /** * @see LogReadable#logEntryIsTransactional */ public boolean logEntryIsTransactional() { return false; } /** * @see LogReadable#getTransactionId */ public long getTransactionId() { return 0; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("time=").append(endTime); sb.append(" lastNodeId=").append(lastNodeId); sb.append(" lastDbId=").append(lastDbId); sb.append(" lastTxnId=").append(lastTxnId); sb.append(" id=").append(id); sb.append(" rootExists=").append(rootLsnExists); sb.append(" ckptStartLsn=").append (DbLsn.getNoFormatString(checkpointStartLsn)); if (rootLsnExists) { sb.append(" root=").append(DbLsn.getNoFormatString(rootLsn)); } sb.append(" firstActive="). append(DbLsn.getNoFormatString(firstActiveLsn)); return sb.toString(); } /* * Accessors */ long getCheckpointStartLsn() { return checkpointStartLsn; } long getRootLsn() { return rootLsn; } long getFirstActiveLsn() { return firstActiveLsn; } long getLastNodeId() { return lastNodeId; } int getLastDbId() { return lastDbId; } long getLastTxnId() { return lastTxnId; } long getId() { return id; } }